package com.hnichr.ump.onetime.invite.service.impl;

import cn.hutool.core.net.URLDecoder;
import cn.hutool.crypto.SecureUtil;
import cn.hutool.http.HttpUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.hnichr.ump.common.onetime.invite.service.AnnualInviteService;
import com.hnichr.ump.common.onetime.invite.vo.SignVo;
import org.apache.commons.lang3.RandomStringUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.data.redis.core.RedisTemplate;

import java.nio.charset.StandardCharsets;
import java.util.*;
import java.util.concurrent.TimeUnit;

@Service
public class AnnualInviteServiceImpl implements AnnualInviteService {

    private static final Logger logger = LoggerFactory.getLogger(AnnualInviteServiceImpl.class);

    private static final String TOKEN_KEY = "ONETIME::INVITE::WX::TOKEN";

    private static final String TICKET_KEY = "ONETIME::INVITE::WX::TICKET";

    @Value("${wx.invitecard.appid}")
    private String appId;

    @Value("${wx.invitecard.appsecret}")
    private String appSecret;

    @Autowired
    private RedisTemplate<String,String> redisTemplate;

    @Override
    public SignVo sign(String encodedUrl) {
        try{


            String ticket = ticket();
            if(StringUtils.isBlank(ticket)){
                return null;
            }
             String noncestr = RandomStringUtils.randomAlphabetic(16);
            String timestamp = String.valueOf(new Date().getTime());
            String url = URLDecoder.decode(encodedUrl, StandardCharsets.UTF_8);
            TreeMap<String,String> treeMap = new TreeMap<>();
            treeMap.put("noncestr",noncestr);
            treeMap.put("jsapi_ticket",ticket);
            treeMap.put("timestamp",timestamp);
            treeMap.put("url",url);
            List<String> paramList = new ArrayList<>();
            for(Map.Entry<String,String> entry:treeMap.entrySet()){
                paramList.add(entry.getKey()+"="+entry.getValue());
            }
            String param = String.join("&",paramList);
            String signature = SecureUtil.sha1(param);

            logger.error(">>>>>>>>>>param:{}",param);
            logger.error(">>>>>>>>>>signature:{}",signature);

            SignVo signVo = new SignVo();
            signVo.setAppId(appId);
            signVo.setNoncestr(noncestr);
            signVo.setTimestamp(timestamp);
            signVo.setSignature(signature);
            return signVo;
        }
        catch (Exception e){
            return null;
        }
    }

    private String token(){
        String token = redisTemplate.opsForValue().get(TOKEN_KEY);
        if(StringUtils.isNotBlank(token)){
            Long expire = redisTemplate.getExpire(TOKEN_KEY, TimeUnit.SECONDS);
            if(expire!=null&&expire>600){
                return token;
            }
        }
        Map<String,Object> tokenParamMap = new HashMap<>();
        tokenParamMap.put("grant_type","client_credential");
        tokenParamMap.put("appid",appId);
        tokenParamMap.put("secret",appSecret);
        String tokenUrl = "https://api.weixin.qq.com/cgi-bin/token";
        String tokenReturn = HttpUtil.get(tokenUrl,tokenParamMap);
        JSONObject tokenJsonObject = JSON.parseObject(tokenReturn);
        if(tokenJsonObject!=null&&tokenJsonObject.containsKey("access_token")&&tokenJsonObject.containsKey("expires_in")){
            token = tokenJsonObject.getString("access_token");
            long expiresIn = tokenJsonObject.getLongValue("expires_in");
            redisTemplate.opsForValue().set(TOKEN_KEY,token,expiresIn,TimeUnit.SECONDS);
            return token;
        }
        return null;
    }

    private String ticket(){
        String ticket = redisTemplate.opsForValue().get(TICKET_KEY);
        if(StringUtils.isNotBlank(ticket)){
            Long expire = redisTemplate.getExpire(TICKET_KEY, TimeUnit.SECONDS);
            if(expire!=null&&expire>600){
                return ticket;
            }
        }

        String token = token();
        if(StringUtils.isBlank(token)){
            return null;
        }
        Map<String,Object> ticketParamMap = new HashMap<>();
        ticketParamMap.put("access_token",token);
        ticketParamMap.put("type","jsapi");

        String ticketUrl = "https://api.weixin.qq.com/cgi-bin/ticket/getticket";
        String ticketReturn = HttpUtil.get(ticketUrl,ticketParamMap);
        JSONObject ticketJsonObject = JSON.parseObject(ticketReturn);
        if(ticketJsonObject!=null&&ticketJsonObject.containsKey("ticket")&&ticketJsonObject.containsKey("expires_in")){
            ticket = ticketJsonObject.getString("ticket");
            long expiresIn = ticketJsonObject.getLongValue("expires_in");
            redisTemplate.opsForValue().set(TICKET_KEY,ticket,expiresIn,TimeUnit.SECONDS);
            return ticket;
        }
        return null;
    }
}
